import numpy as np
import plotly.graph_objects as go
import plotly.offline
from plotly.subplots import make_subplots
import sympy as sp
from sympy import symbols, exp, sin, cos, pi, I, Heaviside, lambdify, integrate, sqrt
from IPython.display import display, HTML
##Workaround para mostrar fórmulas de LaTeX en Plotly
plotly.offline.init_notebook_mode()
display(HTML(
'<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG"></script>'
))
# Solución:
# a) Señal discreta
x = np.array([1,2,3])
n = np.array([-1,0,1])
fig = go.Figure()
fig.add_trace(go.Scatter(
x=n, y=x,
mode='markers',
marker=dict(size=10, color='lime'),
name='x[n]'
))
for ni, xi in zip(n,x):
fig.add_shape(
type='line',
x0=ni, y0=0, x1=ni, y1=xi,
line=dict(color='lime', width=2)
)
fig.update_layout(
title='Señal discreta con stem plot',
xaxis_title='n',
yaxis_title='x[n]',
template='plotly_dark',
showlegend=False
)
fig.show()
# b) Señal continua simbólica
t = symbols('t')
x1 = t**2
xfun = lambdify(t, x1, 'numpy')
tvals = np.linspace(-5,5,1000)
xvals = xfun(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=xvals,
mode='lines',
name=f'x(t) = {x1}',
line=dict(color='lime', width=2)
))
fig.update_layout(
title='Señal continua y definida simbólicamente',
xaxis_title='t',
yaxis_title='x(t)',
template='plotly_dark'
)
fig.show()
# c) Graficación de ambas
Pregunta 2: Señales exponenciales¶
a) Defina y grafique las siguientes señales exponenciales en el intervalo $[-2, 5]$:
- $x(t) = 3e^{0.4t}$ (crecimiento exponencial)
- $y(t) = 2e^{-0.9t}$ (decaimiento exponencial)
b) Compare ambas señales en la misma gráfica con leyenda.
# Solución:
# a) Definir x(t) y y(t)
t = symbols('t')
x = 3*exp(0.4*t)
y = 2*exp(-0.9*t)
tvals = np.linspace(-4,8,1000)
xfun = lambdify(t, x, 'numpy')
yfun = lambdify(t, y, 'numpy')
xvals = xfun(tvals)
yvals = yfun(tvals)
# b) Graficar ambas señales
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=xvals,
mode='lines',
line=dict(color='lime',width=2),
name=f'x(t) = {x}'
))
fig.add_trace(go.Scatter(
x=tvals, y=yvals,
mode='lines',
line=dict(color='cyan', width=2, dash='dash'),
name=f'y(t) = {y}'
))
fig.update_layout(title='Exponencial creciente y decreciente',
xaxis_title='t',
yaxis_title='Exponenciales',
template='plotly_dark',
hovermode='x unified'
)
fig.show()
Pregunta 3: Comparación señal continua vs discreta¶
a) Defina la señal contínua $y(t) = \cos(t)$ y grafíquela en el intervalo $[0, 10]$.
b) Evalúe la misma función coseno en los puntos discretos $n = [0, 1, 2, ..., 10]$ para obtener $y_1[n] = \cos(n)$.
c) Grafique la versión discreta usando stem plot.
# Solución:
# a) Señal continua cos(t)
import numpy as np
t = symbols('t')
y = cos(t)
tvals = np.linspace(0,10,1000)
yfun = lambdify(t,y,'numpy')
yvals = yfun(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=yvals,
mode='lines',
line=dict(color='cyan', width=2),
name=f'y(t)={y}'
))
fig.update_layout(
title='Señal coseno continua',
xaxis_title='t',
yaxis_title='$cos(t)$',
template='plotly_dark'
)
fig.show()
# b) Versión discreta cos(n)
t_disc = np.linspace(0,10,11)
yvals_disc = yfun(t_disc)
fig1 = go.Figure()
fig1.add_trace(go.Scatter(
x=t_disc, y=yvals_disc,
mode='lines+markers',
line=dict(color='lime', width=2),
marker=dict(size=10),
name=f'y(t)={y}'
))
fig1.update_layout(
title='Señal coseno discreta',
xaxis_title='t',
yaxis_title='$cos[t]$',
template='plotly_dark'
)
fig1.show()
# c) Stem plot de la señal discreta
fig2 = go.Figure()
fig2.add_trace(go.Scatter(
x=t_disc, y=yvals_disc,
mode='markers',
marker=dict(color='#ff2785', size=10),
name=f'y[t]={y}'
))
for ti, yi in zip(t_disc, yvals_disc):
fig2.add_shape(
type='line',
x0=ti, y0=0, x1=ti, y1=yi,
line=dict(color='#ff2785', width=2)
)
fig2.update_layout(
title='Señal coseno discreta',
xaxis_title='t',
yaxis_title='$cos[t]$',
template='plotly_dark'
)
fig2.show()
Pregunta 4: Suma de señales sinusoidales¶
a) Defina la señal $x(t) = \cos(t) + \sin(3t)$.
b) Grafique esta señal en el intervalo $[0, 20]$.
# Solución:
# a) Definir x(t) = cos(t) + sin(3t)
t = symbols('t')
x1 = cos(t)
x2 = sin(3*t)
x = x1 + x2
# b) Graficar en [0, 20]
tvals = np.linspace(0, 20, 2000)
xfun = lambdify(t, x, 'numpy')
xvals = xfun(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=xvals,
mode='lines',
line=dict(color="#FBFF13", width=2),
name=f'x(t) = {x}'
))
fig.update_layout(
title='Suma sinuoidal',
xaxis_title='t',
yaxis_title='$cos(t)+sin(3t)$',
template='plotly_dark'
)
fig.show()
Pregunta 5: Modulación de amplitud¶
a) Defina la señal modulada $x(t) = \cos(100t) \cdot e^{2t}$.
b) Grafique esta señal en el intervalo $[0, 2]$.
# Solución:
# a) Definir señal modulada
t = symbols('t')
x = cos(100*t) * exp(2*t)
# b) Graficar en [0, 2]
tvals = np.linspace(0,2,200)
xfun = lambdify(t, x, 'numpy')
xvals = xfun(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=xvals,
mode='lines',
line=dict(color="#FF2626", width=2),
name=f'x(t) = {x}'
))
fig.update_layout(
title='Señal modulada',
xaxis_title='t',
yaxis_title=f'${sp.latex(x)}$',
template='plotly_dark'
)
fig.show()
Pregunta 6: Señales complejas¶
a) Defina la señal compleja $y(t) = 2e^{j(\pi t + \pi/3)}$.
b) Extraiga las partes real e imaginaria de esta señal.
c) Grafique ambas partes por separado en el intervalo $[0, 2]$ con leyendas apropiadas.
# Solución:
# a) Definir señal compleja
t = symbols('t', real=True)
y = 2*exp(I*(pi*t+(pi/3)))
# b) Extraer partes real e imaginaria
im = sp.im(y)
real = sp.re(y)
# print(sp.latex(real))
# c) Graficar ambas partes
tvals = np.linspace(0, 2, 1000)
imfun = lambdify(t, im, 'numpy')
realfun = lambdify(t, real, 'numpy')
imvals = imfun(tvals)
realsvals = realfun(tvals)
fig1 = go.Figure()
fig1.add_trace(go.Scatter(
x=tvals, y=realsvals,
mode='lines',
line=dict(color="#0EFFFF", width=2),
name=f'Re({y})={real}'
))
fig1.update_layout(
title='Parte real de la función',
xaxis_title='t',
yaxis_title='Re(y(t))',
template='plotly_dark'
)
fig1.show()
fig2 = go.Figure()
fig2.add_trace(go.Scatter(
x=tvals, y=imvals,
mode='lines',
line=dict(color="#FF0E9B", width=2),
name=f'Im({y})={im}'
))
fig2.update_layout(
title='Parte imaginaria de la función',
xaxis_title='t',
yaxis_title='Im(y(t))',
template='plotly_dark'
)
fig2.show()
Parte II: Funciones de encendido¶
Pregunta 7: Función escalón de Heaviside¶
a) Defina simbólicamente la función escalón unitario $u(t) = \text{heaviside}(t)$.
b) Grafique esta función en el intervalo $[-5, 10]$ con límites en $y$ de $[-0.5, 1.5]$.
c) ¿Cuál es el valor de $\text{heaviside}(0)$?
d) Evalúe la función de Heaviside en los puntos discretos $n = [-5, -4, ..., 10]$ y grafique usando stem plot.
# Solución:
# a) Definir función Heaviside
t = symbols('t')
u = Heaviside(t)
# b) Gráfica continua
tvals = np.linspace(-5,10,1000)
ufun = lambdify(t, u, 'numpy')
uvals = ufun(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=uvals,
mode='lines',
line=dict(color='lime', width=2),
name='u(t)'
))
fig.update_yaxes(range=[-0.5,1.5])
fig.update_layout(
title='Función escalon',
xaxis_title='t',
yaxis_title='$u(t)$',
template='plotly_dark'
)
fig.show()
# c) Valor en t=0
print(f"u(0) = {ufun(0)}")
# d) Versión discreta con stem
n = np.arange(-5,11)
uvals_dic = ufun(n)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=n, y=uvals_dic,
mode='markers',
marker=dict(color='cyan', size=10),
name='u[t]'
))
for ni, ui in zip(n,uvals_dic):
fig.add_shape(
x0=ni, x1=ni, y0=0, y1=ui,
type='line',
line=dict(color='cyan', width=2)
)
fig.update_layout(
title='Heaviside discreto',
xaxis_title='n',
yaxis_title='u[t]',
template='plotly_dark'
)
fig.update_yaxes(range=[-0.5,1.5])
fig.show()
u(0) = 0.5
Pregunta 8: Función rampa¶
a) Defina la función rampa como $r(t) = t \cdot \text{heaviside}(t)$.
b) Grafique esta función en el intervalo $[-5, 10]$.
# Solución:
# a) Definir función rampa
t = symbols('t')
r = t * Heaviside(t)
# b) Graficar
tvals = np.linspace(-5,10,1000)
rfun = lambdify(t, r, 'numpy')
rvals = rfun(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=rvals,
mode='lines',
line=dict(color="#fff01d", width=2),
name=f'r(t) = {r}'
))
fig.update_layout(
title='Función rampa',
xaxis_title='t',
yaxis_title='$r(t)$',
template='plotly_dark'
)
fig.show()
Pregunta 9: Pulso rectangular¶
a) Defina un pulso rectangular de duración $T = 2$ centrado en el origen usando: $$p_T(t) = \text{heaviside}(t + T/2) - \text{heaviside}(t - T/2)$$
b) Grafique este pulso en el intervalo $[-5, 10]$ con límites en $y$ de $[-0.5, 1.5]$.
# Solución:
# a) Definir pulso rectangular
t = symbols('t')
T = 2
pT = Heaviside(t + (T/2)) - Heaviside(t-(T/2))
# b) Graficar
tvals = np.linspace(-5,10,1000)
pTfun = lambdify(t, pT, 'numpy')
pTvals = pTfun(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=pTvals,
mode='lines',
line=dict(color='cyan', width=2),
name='pT(t)'
))
fig.update_yaxes(range=[-0.5,1.5])
fig.update_layout(
title='Pulso rectangular de duración T=2',
xaxis_title='t',
yaxis_title='$pT(t)$',
template='plotly_dark'
)
fig.show()
Parte III: Transformaciones de señales¶
Pregunta 10: Operaciones sobre señales¶
Considere la señal base $x(t) = t e^{-t}$.
a) Grafique la señal original en el intervalo $[-3, 3]$ con límites en $y$ de $[-3, 0.5]$.
b) Calcule y grafique la señal reflejada: $x_{\text{reflex}}(t) = x(-t)$.
c) Calcule y grafique la señal trasladada: $x_{\text{tras}}(t) = x(t-2)$.
d) Calcule y grafique la señal ensanchada: $x_{\text{broad}}(t) = x(t/3)$.
# Solución:
# a) Señal original x(t) = t*exp(-t)
t = symbols('t')
x = t * exp(-t)
tvals = np.linspace(-3,3,1000)
xfun = lambdify(t, x, 'numpy')
xvals = xfun(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=xvals,
mode='lines',
line=dict(color='lime', width=2),
name='x(t)'
))
fig.update_yaxes(range=[-3,0.5])
fig.update_layout(
title=f'Señal {x}',
xaxis_title='t',
yaxis_title='x(t)',
template='plotly_dark'
)
fig.show()
# b) Reflexión: x(-t)
x_ref = x.subs(t, -t)
xfun_ref = lambdify(t, x_ref, 'numpy')
xvals_ref = xfun_ref(tvals)
fig1 = go.Figure()
fig1.add_trace(go.Scatter(
x=tvals, y=xvals_ref,
mode='lines',
line=dict(color='lime', width=2),
name='x(-t)'
))
fig1.update_yaxes(range=[-3,0.5])
fig1.update_layout(
title=f'Señal reflejada ({x_ref})',
xaxis_title='t',
yaxis_title='x(-t)',
template='plotly_dark'
)
fig1.show()
# c) Traslación: x(t-2)
x_trans = x.subs(t, t-2)
xfun_trans = lambdify(t, x_trans, 'numpy')
xvals_trans = xfun_trans(tvals)
fig2 = go.Figure()
fig2.add_trace(go.Scatter(
x=tvals, y=xvals_trans,
mode='lines',
line=dict(color='lime', width=2),
name='x(t-2)'
))
fig2.update_yaxes(range=[-3,0.5])
fig2.update_layout(
title=f'Señal transladada ({x_trans})',
xaxis_title='t',
yaxis_title='x(t-2)',
template='plotly_dark'
)
fig2.show()
# d) Ensanchamiento: x(t/3)
x_ensancha = x.subs(t, t/3)
xfun_ensancha = lambdify(t, x_ensancha, 'numpy')
xvals_ensancha = xfun_ensancha(tvals)
fig3 = go.Figure()
fig3.add_trace(go.Scatter(
x=tvals, y=xvals_ensancha,
mode='lines',
line=dict(color='lime', width=2),
name='x(t/3)'
))
fig3.update_yaxes(range=[-3,0.5])
fig3.update_layout(
title=f'Señal ensanchada ({x_ensancha})',
xaxis_title='t',
yaxis_title='x(t/3)',
template='plotly_dark'
)
fig3.show()
Pregunta 11: Descomposición par e impar¶
Toda señal se puede descomponer en una parte par y una parte impar.
a) Para la señal $x(t) = t e^{-t}$ y su reflexión $x_{\text{reflex}}(t)$, calcule:
- Parte par: $x_e(t) = \frac{1}{2}[x(t) + x_{\text{reflex}}(t)]$
- Parte impar: $x_o(t) = \frac{1}{2}[x(t) - x_{\text{reflex}}(t)]$
b) Grafique las tres señales ($x_e(t)$, $x_o(t)$, $x(t)$) en el mismo plot en el intervalo $[-10, 10]$ con límites en $y$ de $[-10, 10]$.
c) Verifique que $x(t) = x_e(t) + x_o(t)$.
# Solución:
# a) Calcular partes par e impar
t = symbols('t')
x = t * exp(-t)
x_ref = x.subs(t, -t)
x_par = 1/2 * (x + x_ref)
x_impar = 1/2 * (x - x_ref)
# b) Graficar las tres señales
tvals = np.linspace(-10, 10, 1000)
xvals = lambdify(t, x, 'numpy')(tvals)
x_par_vals = lambdify(t, x_par, 'numpy')(tvals)
x_impar_vals = lambdify(t, x_impar, 'numpy')(tvals)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=tvals, y=xvals,
mode='lines',
line=dict(color="#d60aff"),
name=f'x(t) = {x}'
))
fig.add_trace(go.Scatter(
x=tvals, y=x_par_vals,
mode='lines',
line=dict(color="#0ae2ff"),
name=f'xpar(t) = {x_par}'
))
fig.add_trace(go.Scatter(
x=tvals, y=x_impar_vals,
mode='lines',
line=dict(color="#ff8513"),
name=f'ximpar(t) = {x_impar}'
))
fig.update_yaxes(range=[-10,10])
fig.update_layout(
title='Descomposición de una señal en parte par e impar',
xaxis_title='t',
yaxis_title='Valor de las señales',
template = 'plotly_dark'
)
fig.show()
# c) Verificar descomposición
suma = x_par + x_impar
suma_vals = lambdify(t, suma, 'numpy')(tvals)
fig1 = go.Figure()
fig1.add_trace(go.Scatter(
x=tvals, y=xvals,
mode='lines',
line=dict(color="#d60aff", width=2),
name=f'x(t)={x}'
))
fig1.add_trace(go.Scatter(
x=tvals, y=suma_vals,
mode='lines',
line=dict(color="#fbff0a", width=2, dash='dash'),
name=f'x_par(t) + x_impar'
))
fig1.update_yaxes(range=[-10,10])
fig1.update_layout(
title='Verificación de la descomposición',
xaxis_title='t',
yaxis_title='Valor de las señales',
template='plotly_dark'
)
fig1.show()
Parte IV: Cálculos de energía y potencia¶
Pregunta 12: Cálculo de RMS de función seno¶
Para una señal sinusoidal $x(t) = \sin(t)$ con período fundamental $T = 2\pi$:
a) Calcule la energía en un período: $$E = \int_0^T x^2(t) \, dt = \int_0^{2\pi} \sin^2(t) \, dt$$
b) Calcule la potencia promedio: $$P = \frac{E}{T} = \frac{E}{2\pi}$$ $$(T = 2\pi)$$
c) Calcule el valor RMS (Root Mean Square): $$\text{RMS} = \sqrt{P}$$
d) Exprese el resultado numéricamente usando aritmética simbólica.
e) Puntos extra si hacen el cálculo de la integral a mano y sacan el valor numérico
# Solución:
# a) Cálculo de energía E
t = symbols('t')
x = sin(t)
T = 2*pi
E = integrate(x**2, (t, 0, T))
# b) Cálculo de potencia P
P = E/T
# c) Cálculo de RMS
RMS = sqrt(P)
# d) Evaluación numérica
print(f'E = {E}')
print(f'P = {P}')
print(f'RMS = {RMS}')
E = pi P = 1/2 RMS = sqrt(2)/2